package com.quantum.adapter
{
	import com.quantum.service.ServiceRegistry;
	import flash.utils.getQualifiedClassName;

	import mx.collections.ArrayCollection;

	public final class DefaultAdapterRegistry implements AdapterRegistry
	{
		private static var _instance:DefaultAdapterRegistry;

		private static var _serviceRegistry:ServiceRegistry;

		public function DefaultAdapterRegistry(singletonToken:SingletonToken)
		{
			_serviceRegistry=ServiceRegistry.getInstance(AdapterFactory);
		}

		public static function get instance():DefaultAdapterRegistry
		{
			if (_instance == null)
			{
				_instance=new DefaultAdapterRegistry(new SingletonToken());
			}
			return _instance;
		}

		public function getAdapterByClass(adaptable:Object, adapterType:Class):Object
		{
			var factory:AdapterFactory=findAdapterFactory(adaptable, getQualifiedClassName(adapterType));
			var result:Object=null;
			if (factory != null && adapterType != null)
			{
				result=factory.getAdapter(adaptable, adapterType);
			}
			if (result == null && adaptable is adapterType)
				return adaptable;
			return result;
		}

		public function getAdapter(adaptable:Object, adapterTypeName:String):Object
		{
			var factory:AdapterFactory=findAdapterFactory(adaptable, adapterTypeName);
			var result:Object=null;
			if (factory != null)
			{
				var clazz:Class=findServiceClass(factory, adapterTypeName);
				if (clazz != null)
					result=factory.getAdapter(adaptable, clazz);
				if (result == null && adaptable is clazz)
					result=adaptable;
			}
			if (result == null && getQualifiedClassName(adaptable) == adapterTypeName)
				return adaptable;
			return result;
		}

		public function hasAdapter(adaptable:Object, adapterTypeName:String):Boolean
		{
			return findAdapterFactory(adaptable, adapterTypeName) != null;
		}

		private function findAdapterFactory(adaptable:Object, adapterTypeName:String):AdapterFactory
		{
			var list:ArrayCollection=_serviceRegistry.getServices(adaptable);
			for each (var value:Object in list)
			{
				if (value is AdapterFactory)
				{
					var factory:AdapterFactory=value as AdapterFactory;
					if (findServiceClass(factory, adapterTypeName) != null)
					{
						return factory;
					}
				}
			}
			return null;
		}

		private function findServiceClass(factory:AdapterFactory, className:String):Class
		{
			if (className == null)
			{
				return null;
			}
			var array:Array=factory.getAdapters();
			for each (var value:Object in array)
			{
				if (value is Class && getQualifiedClassName(value) == className)
				{
					return value as Class;
				}
			}
			return null;
		}

		public function registerAdapters(factory:AdapterFactory, adaptable:Class=null):void
		{
			_serviceRegistry.registerService(factory, adaptable);
		}

		public function unregisterAdapters(factory:AdapterFactory, adaptable:Class=null):void
		{
			//TODO:暂时不实现
		}

	}
}

class SingletonToken
{
}